home *** CD-ROM | disk | FTP | other *** search
- #include "flames.h"
- #include <stdlib.h>
- #include <time.h>
-
- #define Max(x, y) ((x) > (y) ? (x) : (y))
- #define Min(x, y) ((x) < (y) ? (x) : (y))
- #define random(val) (rand() % (val+1))
-
-
- FlameDataRecPtr MakeNewFlames (GrafPtr thePort, Rect *flameBounds,
- short minFlameWidth, short maxFlameWidth,
- double flameDensity, double fadeRate,
- short maxFPS, CTabHandle itsCLUT)
- /* Initialize a structure which contains all the data needed to */
- /* run the flame routines */
- {
- CGrafPtr itsOldPort;
- GDHandle itsOldDevice;
- FlameDataRecPtr F = NULL;
- double DTemp;
- OSErr errCode;
- RGBColor RBlack = {0,0,0};
- unsigned int s;
-
- // initialize the random number generator
- s = (unsigned int) clock();
- srand (s);
-
- F = (FlameDataRecPtr)NewPtrClear (sizeof(FlameDataRec));
-
- if (F)
- {
- F->flameTaskPtr = NULL;
- F->flamePort = thePort;
- F->density = flameDensity * 100;
- F->fireCLUT = itsCLUT;
- F->maxColor = (**itsCLUT).ctSize;
- F->fadePerStep = fadeRate * F->maxColor;
-
- /* Set the frame rate */
- DTemp = (double)60 / (double)maxFPS;
- if ((int)(DTemp + 0.5) > (int)DTemp)
- F->timePerFrame = (int)DTemp+1;
- else
- F->timePerFrame = (int)DTemp;
- F->timePerFrame = Max(1, F->timePerFrame);
-
- // We will draw on the whole buffer, but not copy the bottom line
- F->offRect = *flameBounds;
- F->fireRect = *flameBounds;
- OffsetRect (&F->offRect, -F->offRect.left, -F->offRect.top);
- F->copyRect = F->offRect;
- F->copyRect.bottom -= 1;
-
- // Create the offscreen GWorld which the fire will be calculated on
- errCode = NewGWorld(&F->DrawingArea,8,&F->offRect,F->fireCLUT,NULL, 0);
- if (F->isValid = (errCode == noErr))
- {
- // lock the offscreen pixmap and get a pointer to its drawing area
- F->offPixMap = GetGWorldPixMap(F->DrawingArea);
- LockPixels (F->offPixMap);
-
- // set the dimensions of the buffer
- F->BUF_HEIGHT = flameBounds->bottom - flameBounds->top;
- F->BUF_WIDTH = flameBounds->right - flameBounds->left;
- F->maxFlameWidth = maxFlameWidth;
- F->minFlameWidth = minFlameWidth;
-
- // Get the address of our calculation buffer
- F->basePixels = (unsigned char *)GetPixBaseAddr(F->offPixMap);
- F->BitMapWidth = (**F->offPixMap).rowBytes & 0x7FFF;
-
- // clear the offscreen buffer
- GetGWorld(&itsOldPort,&itsOldDevice);
- SetGWorld (F->DrawingArea, NULL);
- RGBForeColor (&RBlack);
- PaintRect (&F->offRect);
- SetGWorld (itsOldPort, itsOldDevice);
- }
- }
-
- return F;
- }
-
-
-
-
- void FreeFlames (FlameDataRecPtr *F)
- {
-
- if (*F)
- {
- if ((**F).flameTaskPtr)
- {
- DisposePtr((Ptr)(**F).flameTaskPtr);
- (**F).flameTaskPtr = NULL;
- }
-
- if ((**F).isValid)
- {
- UnlockPixels ((**F).offPixMap);
- DisposeGWorld((**F).DrawingArea);
- }
-
- DisposePtr((Ptr)*F);
- *F = NULL;
- }
- }
-
-
- void ChangeFlameDensity (FlameDataRecPtr F, double newDensity)
- {
- if (F)
- F->density = newDensity * 100;
- }
-
-
- void ChangeFlameWidth (FlameDataRecPtr F, short newMinWidth, short newMaxWidth)
- {
- if (F)
- {
- F->maxFlameWidth = newMaxWidth;
- F->minFlameWidth = newMinWidth;
- }
- }
-
-
- void ChangeFlameFadeRate (FlameDataRecPtr F, double newFadeRate)
- {
- if (F)
- F->fadePerStep = newFadeRate * F->maxColor;
- }
-
-
-
- void ChangeFlameFPS (FlameDataRecPtr F, short newFPS)
- {
- double DTemp;
- if (F)
- {
- DTemp = (double)60 / (double)newFPS;
- if ((int)(DTemp + 0.5) > (int)DTemp)
- F->timePerFrame = (int)DTemp+1;
- else
- F->timePerFrame = (int)DTemp;
- }
- }
-
-
-
- void StartFlames (FlameDataRecPtr F)
- {
-
- F->burning = TRUE;
-
-
- }
-
-
-
-
- void StopFlames (FlameDataRecPtr F)
- {
- F->burning = FALSE;
- }
-
-
-
-
- short StepFlames(FlameDataRecPtr register F)
- /* Step the fire by one frame, and return the amount of time remaining */
- /* before the next frame should be drawn (in ticks) */
- {
- register unsigned char *traverse;
- register short x, y;
- register short BUF_HEIGHT = F->BUF_HEIGHT,
- BUF_WIDTH = F->BUF_WIDTH;
- long StartTime, Duration;
- short step, color;
- unsigned char *limit;
- unsigned char *limit2;
-
- // if we have stopped burning, return 0; this will cause
- // the VBL Task to terminate
- if (!F->burning)
- return 0;
-
- StartTime = TickCount();
-
- // Transform current buffer
- traverse = F->basePixels + F->BitMapWidth + 1;
- for(y=1;y<BUF_HEIGHT;y++)
- {
- for(x=1;x<BUF_WIDTH-1;x++)
- {
- *(traverse - F->BitMapWidth) = (*traverse + // x, y-1
- *(traverse - 1) + // x, y
- *(traverse + 1) + // x-1, y
- *(traverse + F->BitMapWidth)) >> 2;// x+1, y
-
- *traverse = Max (*traverse - F->fadePerStep, 0);
-
- traverse++;
- }
- traverse += (2 + F->BitMapWidth - BUF_WIDTH);
- }
-
-
- // Set new bottom lines with random white or black
- traverse = F->basePixels + (long)F->BitMapWidth * ((long)BUF_HEIGHT - 2);
- limit = F->basePixels + (long)F->BitMapWidth * ((long)BUF_HEIGHT - 1);
- while (traverse < limit)
- {
- step = random(F->maxFlameWidth - F->minFlameWidth)+F->minFlameWidth;
- if (random(100) < F->density)
- color = F->maxColor;
- else
- color = 0;
-
- limit2 = traverse+step;
- while ((traverse < limit2) && (traverse < limit))
- {
- *traverse = *(traverse + F->BitMapWidth) = color;
- traverse++;
- }
- }
-
- // static long count = 0;
-
- // count++;
- // if((count % 10) == 0){
-
- CopyBits ((const BitMap *)*F->offPixMap, &F->flamePort->portBits,
- &F->copyRect, &F->fireRect, srcCopy, NULL);
- // }
-
- Duration = TickCount() - StartTime;
-
- return Max (1, F->timePerFrame - Duration);
- }
-
-
-
-
-
- static void LockHandle(Handle h)
- {
- if(h){
- HLock(h);
- }
- }
-
- static void UnlockHandle(Handle h)
- {
- if(h){
- HUnlock(h);
- }
- }
-
- static void UnlockPixMap(PixMapHandle p)
- {
- if(p){
- UnlockHandle((Handle)p);
- UnlockHandle((Handle)p[0]->pmTable);
- }
- }
-
- static void LockPixMap(PixMapHandle p)
- {
- if(p){
- LockHandle((Handle)p);
- LockHandle((Handle)p[0]->pmTable);
- }
- }
-
- static void LockPixPat(PixPatHandle p)
- {
- if(p){
- LockHandle((Handle)p);
- LockPixMap(p[0]->patMap);
- LockHandle((Handle)p[0]->patData);
- LockHandle((Handle)p[0]->patXData);
- LockHandle((Handle)p[0]->patXMap);
- }
- }
-
-
- void LockFlames(FlameDataRecPtr inFlames)
- {
-
- LockHandle((Handle)inFlames->DrawingArea->grafVars);
- LockHandle((Handle)inFlames->DrawingArea->visRgn);
- LockHandle((Handle)inFlames->DrawingArea->clipRgn);
- LockPixPat(inFlames->DrawingArea->bkPixPat);
- LockPixPat(inFlames->DrawingArea->pnPixPat);
- LockPixPat(inFlames->DrawingArea->fillPixPat);
-
-
- LockHandle((Handle)inFlames->fireCLUT);
- LockPixMap(inFlames->offPixMap);
-
-
-
- }
-
-
-